﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using Xceed.Silverlight.Data.Stats;

namespace Xceed.Silverlight.Data
{
  internal struct StatParameters
  {
    #region Static Fields

    private static readonly StatFunctionComparer StatFunctionComparerInstance = new StatFunctionComparer();

    #endregion

    #region Constructors

    internal StatParameters( IEnumerable<StatFunction> statFunctions )
      : this( statFunctions, ( DataSourceContext )null )
    {
    }

    internal StatParameters(
      IEnumerable<StatFunction> statFunctions,
      DataPath targetPath )
      : this( statFunctions, targetPath, null )
    {
    }

    internal StatParameters(
      IEnumerable<StatFunction> statFunctions,
      DataSourceContext context )
      : this( statFunctions, DataPath.Empty, context )
    {
    }

    internal StatParameters(
      IEnumerable<StatFunction> statFunctions,
      DataPath targetPath,
      DataSourceContext context )
      : this()
    {
      if( statFunctions == null )
        throw new ArgumentNullException( "statFunctions" );

      if( targetPath == null )
        throw new ArgumentNullException( "targetPath" );

      this.StatFunctions = statFunctions;
      this.TargetPath = targetPath;
      this.Context = context;
    }

    #endregion

    #region StatFunction Property

    internal IEnumerable<StatFunction> StatFunctions
    {
      get;
      private set;
    }

    #endregion

    #region GroupValues Property

    internal IEnumerable<object> GroupValues
    {
      get
      {
        return this.TargetPath.Path
          .Where( ( dataItem ) => dataItem is GroupDataItem )
          .Select( ( groupItem ) => groupItem.Data );
      }
    }

    #endregion

    #region TargetPath Property

    internal DataPath TargetPath
    {
      get;
      private set;
    }

    #endregion

    #region Context Property

    internal DataSourceContext Context
    {
      get;
      private set;
    }

    #endregion

    public override bool Equals( object obj )
    {
      if( !( obj is StatParameters ) )
        return false;

      StatParameters statParameters = ( StatParameters )obj;

      return ( object.Equals( this.TargetPath, statParameters.TargetPath ) )
          && ( object.Equals( this.Context, statParameters.Context ) )
          && ( this.StatFunctions.SequenceEqual( statParameters.StatFunctions, StatParameters.StatFunctionComparerInstance ) );
    }

    public override int GetHashCode()
    {
      if( m_hashCode == null )
      {
        m_hashCode = this.TargetPath.GetHashCode();

        foreach( StatFunction function in this.StatFunctions )
        {
          m_hashCode ^= function.GetEquivalenceKey();
        }
      }

      return m_hashCode.Value;
    }

    public static bool operator ==( StatParameters p1, StatParameters p2 )
    {
      return object.Equals( p1, p2 );
    }

    public static bool operator !=( StatParameters p1, StatParameters p2 )
    {
      return !object.Equals( p1, p2 );
    }

    #region Private Fields

    private Nullable<int> m_hashCode;

    #endregion

    #region StatFunctionComparer Nested Type

    private class StatFunctionComparer : IEqualityComparer<StatFunction>
    {
      public int GetHashCode( StatFunction obj )
      {
        return obj.GetEquivalenceKey();
      }

      public bool Equals( StatFunction x, StatFunction y )
      {
        return StatFunction.AreEquivalents( x, y );
      }
    }

    #endregion
  }
}
